package com.xinhua.erp.service;

import com.xinhua.erp.pojo.*;
import com.xinhua.erp.repo.AccountRepo;
import com.xinhua.erp.repo.PayRepo;
import com.xinhua.erp.repo.SupplierRepo;
import com.xinhua.erp.utils.IdWorker;
import com.xinhua.erp.utils.OrderNumber;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class PayService {

    @Autowired
    private PayRepo payRepo;

    @Autowired
    private SupplierRepo supplierRepo;

    @Autowired
    private AccountRepo accountRepo;

    @Autowired
    private IdWorker idWorker;

    public Result findById(long id){

        return Result.OK(payRepo.getOne(id));
    }


    public Result findAllByType(String type) {

        List<Pay> list = payRepo.findAllByType(type);

        return Result.OK(list);

    }

    public Result findPayByType(String type,int page,int size){

        Pageable pageable = PageRequest.of(page-1, size);

        Page<Pay> pays = payRepo.findAllByType(type, pageable);

        PageResult<Pay> pageResult = new PageResult<>(pays.getTotalElements(), pays.getContent());

        return Result.OK(pageResult);
    }

    public Result deleteById(long id){

        payRepo.deleteById(id);

        return Result.OK();
    }

    public Result save(Pay pay){

        pay.setId(idWorker.nextId());

        pay.setTime(LocalDateTime.now());

        if ("收款".equals(pay.getType())){
            pay.setSerialno(OrderNumber.getSkNumber());

            //供应商/客户金额变动
            Supplier one = supplierRepo.getOne(pay.getSupplierId());

            one.setAllneedpay(one.getAllneedpay().subtract(pay.getAmount()));

            supplierRepo.save(one);

            Account account = accountRepo.getOne(pay.getAccountId());

            account.setCurrentAccountBalance(account.getCurrentAccountBalance().add(pay.getAmount()));

            accountRepo.save(account);

        }else {
            pay.setSerialno(OrderNumber.getFkNumber());

            Supplier one = supplierRepo.getOne(pay.getSupplierId());

            one.setAllneedget(one.getAllneedget().subtract(pay.getAmount()));

            supplierRepo.save(one);

            Account account = accountRepo.getOne(pay.getAccountId());

            account.setCurrentAccountBalance(account.getCurrentAccountBalance().subtract(pay.getAmount()));

            accountRepo.save(account);
        }

        //设置默认值

        payRepo.save(pay);

        return Result.OK();
    }

    public Result update(Long id,Pay pay){
        pay.setId(id);
        payRepo.save(pay);
        return Result.OK();
    }


    public Result Search(Map searchMap, int page, int size) {

        Pageable pageable = PageRequest.of(page - 1, size);

        Page<Pay> pays = payRepo.findAll(createSpecification(searchMap), pageable);

        return Result.OK(new PageResult<>(pays.getTotalElements(), pays.getContent()));
    }

    private Specification<Pay> createSpecification(Map searchMap){
        return new Specification<Pay>() {
            @Override
            public Predicate toPredicate(Root<Pay> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                ArrayList<Predicate> predicateList = new ArrayList<>();

                if(!StringUtils.isBlank((String)searchMap.get("type"))){
                    predicateList.add(criteriaBuilder.like(root.get("type").as(String.class),"%"+searchMap.get("type")+"%"));
                }

                if(!StringUtils.isBlank((String)searchMap.get("serialno"))){
                    predicateList.add(criteriaBuilder.like(root.get("serialno").as(String.class),"%"+searchMap.get("serialno")+"%"));
                }

                if(!StringUtils.isBlank((String)searchMap.get("time"))){
                    predicateList.add(criteriaBuilder.like(root.get("time").as(String.class),"%"+searchMap.get("time")+"%"));
                }

                return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };
    }

}
